Шаг 2. Создаём точную копию коммитов

Создадим новую ветку с названием 04-demo-cherry-pick и сразу на неё переключимся. Для этого воспользуемся командой git switch --create 04-demo-cherry-pick.

Мы внесём изменения и на этой ветке, и на ветке main.

Введена команда git switch --create 04-demo-cherry-pick
Введена команда git switch --create 04-demo-cherry-pick

Далее нам нужно внести изменения в index.html. Обернём элемент <h1> в элемент <header>, а затем добавим для <header> атрибут class со значением site-header.

Красная стрелка указывает на добавленный элемент header
Красная стрелка указывает на добавленный элемент header

После этого добавим изменения в индекс и одновременное зафиксируем, воспользовавшись командой git commit --all --message "feat: added header element". Эта команда будет работать только для уже отслеживаемых файлов. Если файлы ещё не отслеживаются Git, то нужно будет использовать сначала git add, а уже потом git commit.

Введена команда git commit --all --message
Введена команда git commit --all --message

Потом переключимся на ветку main с помощью команды git switch main.

Введена команда git switch main
Введена команда git switch main

У нас пропал элемент <header> — переключение прошло успешно. Теперь нам нужно ещё и на этой ветке внести изменения.

Нам нужны изменения только с этой ветки для создания точной копии коммита, но мы решили внести изменение ещё и на прошлой ветке, чтобы демонстрация была больше похоже на рабочую обстановку.

Элемент <p> и <a> мы обернём в элемент <main>, которому также зададим атрибут class со значением site-main.

Красная стрелка указывает на добавленный элемент main
Красная стрелка указывает на добавленный элемент main

Далее одновременно добавим изменения в индекс и зафиксируем их — git commit --all --message "feat: added main element".

Введена команда git commit --all --message
Введена команда git commit --all --message

Теперь нам нужно посмотреть хэш этого коммита, чтобы позже его использовать вместе с командой git cherry-pick. Для этого пропишем команду git log --oneline -1.

Не очищайте командную строку, чтобы не забыть хэш коммита — он нам понадобится!

Введена команда git log --oneline -1
Введена команда git log --oneline -1

Хэш коммита мы узнали — 1ec11bf. Далее нам нужно переключиться обратно на ветку 04-demo-cherry-pick, поэтому используем команду git switch -.

Введена команда git switch -
Введена команда git switch -

Переходим к созданию копии коммита, сделанного на ветке main.

Перед тем, как мы пропишем команду git cherry-pick, расскажем про опции, которые она может принимать.

  • --edit, сокращённо -e. Позволяет изменить текст коммита. После ввода команды с этой опцией откроется файл COMMIT_EDITMSG, в котором можно отредактировать текст коммита. С этим файлом мы уже сталкивались ранее, например, когда добавляли изменения в последний коммит.
  • --no-commit, сокращённо -n. С её помощью изменения будут просто перенесены и добавлены в индекс — далее вы сами можете их зафиксировать с помощью команды git commit. Опцию --no-commit с командой git cherry-pick можно заменить на другую команду — git checkout хэш-коммита *. Звёздочка обязательна — если вы её не напишите, то переключитесь на коммит и перейдёте в состояние detached HEAD. Что это такое и зачем нужно, разберём в другом разделе.

Также отметим: для git cherry-pick можно передавать не один хэш, а начальный и конечный. Запись будет такой: git cherry-pick начальный-хэш конечный-хэш. В таком случае вы скопируете все коммиты от указанного в начале до конечного включительно.

Нам группа коммитов не нужна, да и опции тоже, поэтому просто пропишем команду git cherry-pick 1ec11bf. Хэш коммита указываем тот, который ранее посмотрели через команду git log.

Введена команда git cherry-pick 1ec11bf
Введена команда git cherry-pick 1ec11bf

Возник конфликт. Мы специально его создали, чтобы показать, что конфликты происходят не только при git rebase или git merge, но ещё и при git cherry-pick. При использовании этой команды происходит слияние, о чём нам говорит первая выведенная строчка Auto-merging index.html. Поэтому и возникают конфликты.

Решать конфликт мы будем не с помощью Merge Editor от VS Code, а вручную — так мы можем сделать всё как нужно. После внесённых изменений получился вот такой код:

Код после внесённых изменений
Код после внесённых изменений

То есть мы обернули <h1> в элемент <header>, а весь оставшийся контент — в элемент <main>.

После решения конфликта нам нужно продолжить копирование коммита.

После решения конфликта можно прописать git cherry-pick --quit. Эта команда работает только для группы коммитов, она позволяет сбросить запомненное состояние и остановить копирование коммитов. То есть те коммиты, которые успели скопироваться до возникновения конфликта, так и останутся. Но после решения конфликта копирование коммитов будет прервано, и оставшаяся часть не будет скопирована и перенесена.

Вернёмся к нашему конфликту. Добавим изменения в индекс с помощью команды git add --all.

Введена команда git add --all
Введена команда git add --all

Продолжим создание копии коммита, для этого воспользуемся командой git cherry-pick --continue.

Введена команда git cherry-pick --continue
Введена команда git cherry-pick --continue

После ввода команды открылся файл COMMIT_EDITMSG, в котором можно отредактировать текст коммита. Нам этот текст редактировать не нужно. Мы просто сохраним файл с помощью сочетания клавиш Ctrl + S, а затем закроем его, нажав на крестик.

Перейдём обратно в Git Bash и увидим в выводе, что коммит создан.

Вывод Git после использования команды git cherry-pick
Вывод Git после использования команды git cherry-pick

Теперь давайте выведем последние коммиты, чтобы посмотреть на хэш скопированного коммита. Для этого пропишем команду git log --oneline -2.

Введена команда git log --oneline -2
Введена команда git log --oneline -2

Хэш коммита совсем другой: раньше был 1ec11bf, а теперь 6109857. Также после создания копии коммита был сгенерирован идентификатор исправления — он поможет нам, когда мы будем выполнять перебазирование.